package com.weharvest.edu.service.Impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.weharvest.edu.constant.MenuConstant;
import com.weharvest.edu.dao.BackstageRoleDao;
import com.weharvest.edu.dao.mapper.BackstageRoleAndMenuAndPermissionDaoMapper;
import com.weharvest.edu.dao.mapper.BackstageRoleDaoMapper;
import com.weharvest.edu.dao.mapper.BackstageUserDaoMapper;
import com.weharvest.edu.dao.mapper.BaseDaoMapper;
import com.weharvest.edu.dto.BackstageRoleAndMenuAndPermissionDTO;
import com.weharvest.edu.dto.BackstageRoleDTO;
import com.weharvest.edu.entity.BackstageMenu;
import com.weharvest.edu.entity.BackstageRole;
import com.weharvest.edu.enums.CommonEnums;
import com.weharvest.edu.enums.ResultEnum;
import com.weharvest.edu.exception.EduException;
import com.weharvest.edu.service.BackstageRoleService;
import com.weharvest.edu.utlis.SessionUtil;
import com.weharvest.edu.view.BackstagePermissionView;
import com.weharvest.edu.view.BackstageRoleAndMenuAndPermissionOneView;
import com.weharvest.edu.view.BackstageRoleAndMenuAndPermissionView;
import com.weharvest.edu.view.BackstageRoleStructureView;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.transaction.Transactional;
import java.util.*;
import java.util.stream.Collectors;


@Service
@Slf4j
public class BackstageRoleServiceImpl extends BaseServiceImpl implements BackstageRoleService {

    @Resource
    private BackstageRoleDao backstageRoleDao;

    @Resource
    private BackstageRoleAndMenuAndPermissionDaoMapper BrmpDaoMapper;

    @Resource
    private BackstageRoleDaoMapper backstageRoleDaoMapper;


    @Resource
    private BackstageUserDaoMapper userDaoMapper;

    @Override
    public Map<String, Object> findByAll(
            BackstageRoleDTO dto,
            HttpServletRequest request, HttpServletResponse response) {
        Map<String, Object> params = new HashMap<>();
        Map<String, Object> result = new HashMap<>();
        Map<String, Object> paramsByBr = new HashMap<>();
        if (null == dto) {
            log.error("[后台角色管理]查询角色列表，输入参数不能为空");
            throw new EduException(ResultEnum.BACKSTAGEROLE_FIND_INPUT_NODATA);
        }
        String uid = SessionUtil.getSession(request, "uid");
        String organizationId = SessionUtil.getSession(request, "organizationId");
        //根据中间表查询该角色
        paramsByBr.put("userId", uid);
        paramsByBr.put("organizationId", organizationId);
        paramsByBr.put("flag", CommonEnums.flag.FLAG_AVAILABLE.getCode());
        BackstageRole backstageRole = userDaoMapper.queryByBr(paramsByBr);

        //根据该角色拥有的下级列表
        PageHelper.startPage(dto.getPageNo(), dto.getPageSize(), "create_time desc");
        params.put("likeByPid", backstageRole.getPid());
        params.put("flag", CommonEnums.flag.FLAG_AVAILABLE.getCode());
        params.put("likeByName", dto.getLikeName());
        result.put("data", new PageInfo<BackstageRole>(
                backstageRoleDaoMapper.findByParams(params)));
        return result;
    }


    @Override
    @Transactional
    public void authorizationByAdd(
            BackstageRoleAndMenuAndPermissionDTO brmp) {
        if (brmp == null) {
            throw new EduException(ResultEnum.AUTHORIZATION_ERROR);
        }
        //删除该角色原有的所有角色菜单和角色菜单资源中间表
        BrmpDaoMapper.deleteByBackstageRoleMenu(brmp.getRoleId());
        BrmpDaoMapper.deleteByBackstageRoleMenuPermission(brmp.getRoleId());

        //增加权限
        BrmpDaoMapper.batchAddByBackstageRoleMenu(brmp);
        BrmpDaoMapper.batchAddByBackstageRoleMenuPermission(brmp);
        return;
    }

    @Override
    public BackstageRoleAndMenuAndPermissionView authorizationByFind(BackstageRoleDTO backstageRoleDTO) {
        //获取当前角色所用有的菜单列表
        BackstageRole backstageRole = new BackstageRole();
        BeanUtils.copyProperties(backstageRoleDTO, backstageRole);
        List<BackstageMenu> menus =
                BrmpDaoMapper.queryByBackstageMenu(backstageRole);
        if (menus.isEmpty() || menus == null) {
            return null;
        }
        //获取权限
        List<BackstagePermissionView> backstagePermissionViewList =
                BrmpDaoMapper.queryByBackstagePermissionView(backstageRole, menus);

        // 处理数据结构
        Queue<BackstageRoleAndMenuAndPermissionView> queue = new LinkedList<>();
        //初始化值
        List<BackstageMenu> initMenus = menus;
        //保存剩下
        List<BackstageMenu> save = new ArrayList<>();
        //取出根目录
//      List<String> names =students.stream().map(Student::getName).collect(Collectors.toList())；
        BackstageRoleAndMenuAndPermissionView bramapRoot =
                new BackstageRoleAndMenuAndPermissionView();
        bramapRoot.setId(MenuConstant.ROOT);
        bramapRoot.setName("根目录");
        queue.offer(bramapRoot);

        while (!queue.isEmpty()) {
            List<BackstageRoleAndMenuAndPermissionView> bramapList = new ArrayList<>();
            //取出队列
            BackstageRoleAndMenuAndPermissionView root = queue.poll();
            for (BackstageMenu backstageMenu : initMenus) {
                //拆分pid
                String indexs[] = backstageMenu.getPid().split("/");
                //是否存在下级
                if (indexs[indexs.length - 2].equals(root.getId().toString())) {
                    BackstageRoleAndMenuAndPermissionView bramap =
                            new BackstageRoleAndMenuAndPermissionView();
                    bramap.setId(backstageMenu.getId());
                    bramap.setName(backstageMenu.getName());
                    // 设置
                    bramapList.add(bramap);
                    root.setChildren(bramapList);
                    //塞入队列
                    queue.offer(bramap);
                } else {
                    //保存
                    save.add(backstageMenu);
                }
            }
            //清空遍历次数
            initMenus.clear();
            initMenus.addAll(save);
            //清空
            save.clear();
        }
        //permission假如没有查看这个功能就截止这个菜单


        return recursionFindChildren(bramapRoot, backstagePermissionViewList);
    }


    @Override
    public BackstageRoleAndMenuAndPermissionOneView authorizationByFindOne(BackstageRoleDTO backstageRoleDTO) {
        //获取当前角色所用有的菜单列表
        BackstageRole backstageRole = new BackstageRole();
        BeanUtils.copyProperties(backstageRoleDTO, backstageRole);
        List<BackstageMenu> menus =
                BrmpDaoMapper.queryByBackstageMenu(backstageRole);
        if (menus.isEmpty() || menus == null) {
            return new BackstageRoleAndMenuAndPermissionOneView();
        }
        //获取权限
        List<BackstagePermissionView> backstagePermissionViewList =
                BrmpDaoMapper.queryByBackstagePermissionView(backstageRole, menus);
        List<String> result = new ArrayList<>();
        BackstageRoleAndMenuAndPermissionOneView bramapov =
                new BackstageRoleAndMenuAndPermissionOneView();
        for (BackstagePermissionView bpv : backstagePermissionViewList) {
            //合拼
            String select = bpv.getMenuId().concat("-" + bpv.getId());
            result.add(select);
        }
        bramapov.setMenus(result);
        return bramapov;
    }


    /**
     * 递归查询是否存在下级
     *
     * @param bramapv
     * @param bpvList
     * @return
     */
    private BackstageRoleAndMenuAndPermissionView recursionFindChildren(
            BackstageRoleAndMenuAndPermissionView bramapv,
            List<BackstagePermissionView> bpvList) {

        // 存在下级就不设置
        if (bramapv != null && !bramapv.getChildren().isEmpty()) {
            // 递归
            bramapv.getChildren().stream().map(e -> recursionFindChildren(e, bpvList)).collect(Collectors.toList());
            return bramapv;
        }
        // 是否最后一个节点
        List<BackstageRoleAndMenuAndPermissionView> addPermission = new ArrayList<>();
        for (BackstagePermissionView bpv : bpvList) {
            //设置该菜单属于权限
            if (bpv.getMenuId().equals(bramapv.getId())) {
                // 拼接字符串给前端做识别和分割
                BackstageRoleAndMenuAndPermissionView bpvPermission =
                        new BackstageRoleAndMenuAndPermissionView();
                bpvPermission.setId(bpv.getMenuId() + '-' + bpv.getId());
                bpvPermission.setName(bpv.getName());
                addPermission.add(bpvPermission);
            }
        }
        bramapv.setChildren(addPermission);
        return bramapv;
    }

    @Override
    @Transactional
    public void delete(BackstageRoleDTO dto,
                       HttpServletRequest request, HttpServletResponse response) {
        Map<String, Object> paramsByBR = new HashMap<>();
        Map<String, Object> params = new HashMap<>();

        if (null == dto || StringUtils.isEmpty(dto.getTargetId())) {
            log.error("[后台角色管理]删除角色，输入参数不合法");
            throw new EduException(ResultEnum.BACKSTAGEROLE_DETELE_INPUT_NODATA);
        }
        String uid = SessionUtil.getSession(request, "uid");
        //验证本角色是否存在
        paramsByBR.put("userId", uid);
        paramsByBR.put("flag", CommonEnums.flag.FLAG_AVAILABLE.getCode());
        paramsByBR.put("state", CommonEnums.state.STATE_AVAILABLE.getCode());
        BackstageRole backstageRole = userDaoMapper.queryByBr(paramsByBR);

        if (null == backstageRole) {
            log.error("[后台角色管理]删除角色，该角色不存在");
            throw new EduException(ResultEnum.BACKSTAGEROLE_FIND_RESULT_NODATA);
        }

        // 查询目标是否存在
        BackstageRole targetRole = backstageRoleDao.findByIdAndFlag(
                dto.getTargetId(),
                CommonEnums.flag.FLAG_AVAILABLE.getCode());
        if (targetRole == null) {
            throw new EduException(ResultEnum.BACKSTAGEROLE_TARGET_NO_EXIST);
        }

        //校验源角色是否存在目标角色
        List<BackstageRole> existList = backstageRoleDao.parentExistChildren(
                backstageRole.getId(),
                targetRole.getId(),
                CommonEnums.flag.FLAG_AVAILABLE.getCode());
        if (existList.size() == 0 || existList.isEmpty()) {
            throw new EduException(ResultEnum.BACKSTAGEROLE_EXIST);
        }

        //删除目标角色
        targetRole.setId(dto.getTargetId());
        targetRole.setFlag(CommonEnums.flag.FLAG_NO_AVAILABLE.getCode());
        targetRole.setUpdateTime(new Date());
        targetRole = backstageRoleDao.save(targetRole);

        //清除角色菜单和角色菜单资源中间表
        BrmpDaoMapper.deleteByBackstageRoleMenu(targetRole.getId());
        BrmpDaoMapper.deleteByBackstageRoleMenuPermission(targetRole.getId());

        //并清除关联这个角色的所有用户

        return;
    }

    @Override
    @Transactional
    public void modify(BackstageRoleDTO backstageRoleDTO) {
        if (null == backstageRoleDTO || StringUtils.isEmpty(backstageRoleDTO.getId())) {
            log.error("[后台角色管理]修改角色，输入参数不能为空");
            throw new EduException(ResultEnum.BACKSTAGEROLE_MODIFY_INPUT_NODATA);
        }
        BackstageRole backstageRole = new BackstageRole();
        backstageRole = backstageRoleDao.findById(backstageRoleDTO.getId()).get();
        if (null == backstageRole) {
            log.error("[后台角色管理]修改角色，返回数据不合法");
            throw new EduException(ResultEnum.BACKSTAGEROLE_MODIFY_RESULT_NODATA);
        }
        //判断是否禁用的请求
        if (backstageRoleDTO.getState() != null) {
            backstageRole.setState(backstageRoleDTO.getState());
            backstageRoleDao.save(backstageRole);
            return;
        }
        BeanUtils.copyProperties(backstageRoleDTO, backstageRole);
        backstageRole.setFlag(CommonEnums.flag.FLAG_AVAILABLE.getCode());
        backstageRole.setState(CommonEnums.state.STATE_AVAILABLE.getCode());
        backstageRole.setUpdateTime(new Date());
        backstageRole = backstageRoleDao.save(backstageRole);
        return;
    }


    @Override
    @Transactional
    public void add(BackstageRoleDTO backstageRoleDTO, HttpServletRequest request) {
        if (null == backstageRoleDTO) {
            log.error("[后台角色管理]新增角色，输入参数不能为空");
            throw new EduException(ResultEnum.BACKSTAGEROLE_ADD_INPUT_NODATA);
        }
        String uid = SessionUtil.getSession(request, "uid");
        //查看继承id的信息
        BackstageRole extendsBackstageRole =
                backstageRoleDao.findByIdAndStateAndFlag(
                        uid,
                        CommonEnums.state.STATE_AVAILABLE.getCode(),
                        CommonEnums.flag.FLAG_AVAILABLE.getCode());
        if (null == extendsBackstageRole) {
            log.error("[后台角色管理]新增角色，输入参数不能为空");
            throw new EduException(ResultEnum.BACKSTAGEROLE_ADD_RESULT_NODATA);
        }
        BackstageRole backstageRole = new BackstageRole();
        BeanUtils.copyProperties(backstageRoleDTO, backstageRole);
        backstageRole.setFlag(CommonEnums.flag.FLAG_AVAILABLE.getCode());
        backstageRole.setState(CommonEnums.state.STATE_NO_AVAILABLE.getCode());
        backstageRole.setCreateTime(new Date());
        List<BackstageRole> newBackstageRole = backstageRoleDao.findAll();
        backstageRole.setPid(extendsBackstageRole.getPid() + "/" +
                (newBackstageRole.size() + CommonEnums.number.DEFAULT_NUMBER_ONE.getCode()));
        backstageRole.setId("R" +
                (newBackstageRole.size() + CommonEnums.number.DEFAULT_NUMBER_ONE.getCode()));
        backstageRoleDao.save(backstageRole);
        return;
    }

    //处理结构
    private BackstageRoleStructureView handle(BackstageRole root, List<BackstageRole> backstageRoleList) {
        BackstageRoleStructureView backstageRoleStructureView = new BackstageRoleStructureView();
        //塞进队列
        Queue<BackstageRoleStructureView> rootQueue = new LinkedList<>();
        BeanUtils.copyProperties(root, backstageRoleStructureView);
        rootQueue.offer(backstageRoleStructureView);
        //保存剩下的节点
        List<BackstageRole> save = new ArrayList<>();
        //初始化值
        List<BackstageRole> initialization = backstageRoleList;
        while (!rootQueue.isEmpty()) {
            //设置下级
            List<BackstageRoleStructureView> childViewList = new ArrayList<>();
            //取出元素
            BackstageRoleStructureView rootBackstageRoleStructureView = rootQueue.poll();
            //遍历剩下的节点
            for (BackstageRole backstageRole : initialization) {
                //拆分pid值
                String indexs[] = backstageRole.getPid().split("/");
                if (indexs[indexs.length - 2].equals(rootBackstageRoleStructureView.getId().toString())) {
                    //设置下级
                    BackstageRoleStructureView childView = new BackstageRoleStructureView();
                    BeanUtils.copyProperties(backstageRole, childView);
                    childViewList.add(childView);
                    //设置
                    rootBackstageRoleStructureView.setChild(childViewList);
                    //添加当前节点入队列
                    rootQueue.offer(childView);
                } else {
                    //保存剩下的节点
                    save.add(backstageRole);
                }
            }
            //重新赋值
            initialization.clear();
            initialization.addAll(save);
            //清空
            save.clear();
        }
        return backstageRoleStructureView;
    }

    @Override
    public BaseDaoMapper init() {
        return backstageRoleDaoMapper;
    }
}
